package msgdef

import (
	"encoding/binary"
	"errors"
	"fmt"
	"src/zeus/bytestream"
)

/*
	msgdef 包下面主要定义二进制消息流
	由于二进制消息流个数固定，所以在代码中直接定义，序列化和反序列化
*/

/////////////////////////////////////////////////////////////////////////////

// MatchPlayerInfo 匹配成功以后发送到战斗服的玩家数据
type MatchPlayerInfo struct {
	NickName string
	EntityID uint64
	DBID     uint64
}

func (msg *MatchPlayerInfo) String() string {
	return fmt.Sprintf("%+v", *msg)
}

// MarshalTo 序列化
func (msg *MatchPlayerInfo) MarshalTo(data []byte) (n int, err error) {
	bw := bytestream.NewByteStream(data)
	return msg.Size(), bw.Marshal(msg)
}

// Unmarshal 反序列化
func (msg *MatchPlayerInfo) Unmarshal(data []byte) error {
	br := bytestream.NewByteStream(data)
	return br.Unmarshal(msg)
}

// Size 获取长度
// 8 + 4 + 2 + len([]byte)
func (msg *MatchPlayerInfo) Size() (n int) {
	return bytestream.CalcSize(msg)
}

// Name 获取名字
func (msg *MatchPlayerInfo) Name() string {
	return "MatchPlayerInfo"
}

/////////////////////////////////////////////////////////////////////////////

// MatchPlayerList 匹配成功以后发送到战斗服的玩家数据列表
type MatchPlayerList struct {
	PlayerList []*MatchPlayerInfo
}

func (msg *MatchPlayerList) String() string {
	return fmt.Sprintf("%+v", *msg)
}

// Name 消息名
func (msg *MatchPlayerList) Name() string {
	return "MatchPlayerList"
}

// MarshalTo 序列化
func (msg *MatchPlayerList) MarshalTo(data []byte) (n int, err error) {
	count := uint16(len(msg.PlayerList))
	binary.LittleEndian.PutUint16(data[0:2], count)
	pos := 2
	for _, v := range msg.PlayerList {
		i, _ := v.MarshalTo(data[pos:])
		pos += i
	}
	return msg.Size(), nil
}

// Unmarshal 反序列化
func (msg *MatchPlayerList) Unmarshal(data []byte) error {
	count := binary.LittleEndian.Uint16(data[0:2])
	pos := 2
	for i := uint16(0); i < count; i++ {
		f := new(MatchPlayerInfo)
		f.Unmarshal(data[pos:])
		msg.PlayerList = append(msg.PlayerList, f)
		pos += f.Size()
		if pos > len(data) {
			return errors.New("MatchPlayerList Unmarshal msg error.")
		}
	}

	return nil
}

// Size 消息长度
// 1 + 8 + 2 + len(string) + 2 + len([]byte)
func (msg *MatchPlayerList) Size() (n int) {
	i := 2
	for _, v := range msg.PlayerList {
		i += v.Size()
	}
	return i
}
